package cn.iocoder.yudao.module.nginxui.service.config;

import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import cn.iocoder.yudao.module.nginxui.controller.admin.config.vo.*;
import cn.iocoder.yudao.module.nginxui.dal.dataobject.config.NginxConfigDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.nginxui.dal.mysql.config.NginxConfigMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.nginxui.enums.ErrorCodeConstants.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * Nginx主配置 Service 实现类
 *
 * @author HuangJunZhong
 */
@Service
@Validated
public class NginxConfigServiceImpl implements NginxConfigService {

    @Resource
    private NginxConfigMapper nginxConfigMapper;

    @Override
    public Long createConfig(ConfigSaveReqVO createReqVO) {
        // 插入
        NginxConfigDO config = BeanUtils.toBean(createReqVO, NginxConfigDO.class);
        // 设置默认值
        if (config.getWorkerProcesses() == null) {
            config.setWorkerProcesses("auto");
        }
        if (config.getWorkerConnections() == null) {
            config.setWorkerConnections(1024);
        }
        if (config.getStatus() == null) {
            config.setStatus(1); // 默认启用
        }
        // 设置默认配置内容
        if (config.getContent() == null || config.getContent().trim().isEmpty()) {
            config.setContent(NginxConfigDO.getDefaultContent());
        }
        nginxConfigMapper.insert(config);

        // 返回
        return config.getId();
    }

    @Override
    public void updateConfig(ConfigSaveReqVO updateReqVO) {
        // 校验存在
        validateConfigExists(updateReqVO.getId());
        // 更新
        NginxConfigDO updateObj = BeanUtils.toBean(updateReqVO, NginxConfigDO.class);


        // 先获取当前的content内容
        NginxConfigDO oldConfig = nginxConfigMapper.selectById(updateObj.getId());
        if (oldConfig != null && updateObj.getContent() == null) {
            updateObj.setContent(oldConfig.getContent());
        }

        // 同步特定字段到content
        syncFieldsToContent(updateObj);





        nginxConfigMapper.updateById(updateObj);
    }





    /**
     * 同步所有字段到content，确保绝对唯一
     */
    private void syncFieldsToContent(NginxConfigDO config) {
        String content = config.getContent();

        // 关键改进：先处理所有配置项的清除逻辑，再统一添加
        // 1. 清除阶段 - 无论是否有新值，先彻底清除所有相关配置
        content = clearConfigItem(content, "worker_processes");
        content = clearConfigItem(content, "error_log");
        content = clearConfigItem(content, "pid");
        content = clearEventsConfig(content, "worker_connections");
        content = clearGlobalInclude(content);
        content = clearHttpInclude(content);

        // 2. 添加阶段 - 只添加有值的配置项
        if (config.getWorkerProcesses() != null && !config.getWorkerProcesses().trim().isEmpty()) {
            content = addConfigItem(content, "worker_processes", config.getWorkerProcesses());
        }
        if (config.getErrorLog() != null && !config.getErrorLog().trim().isEmpty()) {
            content = addConfigItem(content, "error_log", config.getErrorLog());
        }
        if (config.getPid() != null && !config.getPid().trim().isEmpty()) {
            content = addConfigItem(content, "pid", config.getPid());
        }
        if (config.getWorkerConnections() != null) {
            content = addEventsConfig(content, "worker_connections", String.valueOf(config.getWorkerConnections()));
        }
        if (config.getGlobalInclude() != null && !config.getGlobalInclude().trim().isEmpty()) {
            content = addGlobalInclude(content, config.getGlobalInclude());
        }
        if (config.getHttpInclude() != null && !config.getHttpInclude().trim().isEmpty()) {
            content = addHttpInclude(content, config.getHttpInclude());
        }

        config.setContent(content);
    }

    // ------------------------------ 清除逻辑（确保彻底删除） ------------------------------

    /**
     * 清除所有指定的全局配置项
     */
    private String clearConfigItem(String content, String directive) {
        // 增强正则：匹配任何形式的该配置项（包括各种缩进和空格）
        Pattern pattern = Pattern.compile(
                "(?m)^\\s*" + directive + "\\s+[^;]*;\\s*$",  // (?m)启用多行模式
                Pattern.CASE_INSENSITIVE
        );
        content = pattern.matcher(content).replaceAll("");

        // 清理空行
        return cleanEmptyLines(content);
    }

    /**
     * 清除events块中的指定配置项
     */
    private String clearEventsConfig(String content, String directive) {
        Pattern pattern = Pattern.compile(
                "(events\\s*\\{[^}]*?)\\s*" + directive + "\\s+[^;]*;\\s*([^}]*\\})",
                Pattern.DOTALL | Pattern.CASE_INSENSITIVE
        );
        content = pattern.matcher(content).replaceAll("$1$2");

        // 清理events块内的空行
        return cleanEventsBlock(content);
    }

    /**
     * 彻底清除所有global_include块
     */
    private String clearGlobalInclude(String content) {
        Pattern pattern = Pattern.compile(
                "(?m)^\\s*#\\s*global_include_start\\s*$.*?^\\s*#\\s*global_include_end\\s*$",
                Pattern.DOTALL | Pattern.MULTILINE
        );
        content = pattern.matcher(content).replaceAll("");
        return cleanEmptyLines(content);
    }

    /**
     * 彻底清除所有http_include块
     */
    private String clearHttpInclude(String content) {
        Pattern pattern = Pattern.compile(
                "(?m)^\\s*#\\s*http_include_start\\s*$.*?^\\s*#\\s*http_include_end\\s*$",
                Pattern.DOTALL | Pattern.MULTILINE
        );
        content = pattern.matcher(content).replaceAll("");
        return cleanEmptyLines(content);
    }

    // ------------------------------ 添加逻辑（确保位置唯一） ------------------------------

    /**
     * 添加全局配置项（固定位置）
     */
    private String addConfigItem(String content, String directive, String value) {
        String newConfigLine = directive + " " + value + ";";

        // 尝试在events块前插入
        Pattern pattern = Pattern.compile("(\\s*)(events\\s*\\{)", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(content);

        if (matcher.find()) {
            return matcher.replaceFirst(
                    "$1" + newConfigLine + "\n" +  // 新配置
                            "$1$2"                        // 原有events块
            );
        }

        // 没有events块时，添加到文件开头
        return newConfigLine + "\n" + content;
    }

    /**
     * 在events块中添加配置项（固定位置）
     */
    private String addEventsConfig(String content, String directive, String value) {
        String newConfig = "    " + directive + " " + value + ";";

        // 检查是否已有events块
        Pattern pattern = Pattern.compile("(events\\s*\\{)([^}]*)(\\})", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(content);

        if (matcher.find()) {
            String innerContent = matcher.group(2).trim();
            String newInner = innerContent.isEmpty() ? newConfig : newConfig + "\n    " + innerContent;
            return matcher.replaceFirst(matcher.group(1) + "\n" + newInner + "\n" + matcher.group(3));
        }

        // 没有events块则创建
        return content + "\nevents {\n" + newConfig + "\n}";
    }

    /**
     * 添加全局include配置（固定位置）
     */
    private String addGlobalInclude(String content, String includePath) {
        String includeConfig = "\n# global_include_start\ninclude " + includePath + ";\n# global_include_end";

        // 在events块前插入
        Pattern pattern = Pattern.compile("(\\s*)(events\\s*\\{)", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(content);

        if (matcher.find()) {
            return matcher.replaceFirst("$1" + includeConfig + "\n$1$2");
        }

        // 没有events块则添加到文件末尾
        return content + includeConfig;
    }

    /**
     * 添加http include配置（固定位置）
     */
    private String addHttpInclude(String content, String includePath) {
        String includeConfig = "\n    # http_include_start\n    include " + includePath + ";\n    # http_include_end";

        // 在http块末尾插入
        Pattern pattern = Pattern.compile("(http\\s*\\{[^}]*)(\\s*\\})", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(content);

        if (matcher.find()) {
            return matcher.replaceFirst("$1" + includeConfig + "\n$2");
        }

        // 没有http块则创建
        return content + "\nhttp {\n" + includeConfig.substring(1) + "\n}";
    }

    // ------------------------------ 工具方法 ------------------------------

    /**
     * 清理空行（连续空行压缩为一个，去除首尾空行）
     */
    private String cleanEmptyLines(String content) {
        if (content == null || content.isEmpty()) {
            return "";
        }
        // 压缩连续空行
        content = content.replaceAll("(?m)(^\\s*$\\n?)+", "\n");
        // 去除首尾空行
        return content.trim();
    }

    /**
     * 清理events块内的空行
     */
    private String cleanEventsBlock(String content) {
        Pattern pattern = Pattern.compile("(events\\s*\\{)([^}]*)(\\})", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(content);

        if (matcher.find()) {
            String innerContent = matcher.group(2)
                    .replaceAll("(?m)^\\s*$\\n?", "")  // 清除空行
                    .trim();
            return matcher.replaceFirst(matcher.group(1) + "\n    " + innerContent + "\n" + matcher.group(3));
        }
        return content;
    }



    @Override
    public void deleteConfig(Long id) {
        // 校验存在
        validateConfigExists(id);
        // 删除
        nginxConfigMapper.deleteById(id);
    }

    @Override
        public void deleteConfigListByIds(List<Long> ids) {
        // 删除
        nginxConfigMapper.deleteByIds(ids);
        }


    private NginxConfigDO validateConfigExists(Long id) {
        NginxConfigDO nginxConfigDO =  nginxConfigMapper.selectById(id);
        if (nginxConfigDO == null) {
            throw exception(CONFIG_NOT_EXISTS);
        }
        return nginxConfigDO;
    }

    @Override
    public NginxConfigDO getConfig(Long id) {
        return nginxConfigMapper.selectById(id);
    }

    @Override
    public PageResult<NginxConfigDO> getConfigPage(ConfigPageReqVO pageReqVO) {
        return nginxConfigMapper.selectPage(pageReqVO);
    }


    /**
     * 更新主配置的content内容（供其他配置模块同步使用）
     */
    @Override
    public void updateConfigContent(Long id, String content) {
        // 校验存在
        NginxConfigDO config = validateConfigExists(id);

        // 直接更新content字段
        config.setContent(content);
        nginxConfigMapper.updateById(config);
    }

}